Диаграмма с параллельными координатами
Диаграмма parallel (параллельных координат) позволяет визуализировать значения по нескольким признакам (измерениям, переменным) для набора объектов. Каждый признак представлен своей вертикальной или горизонтальной осью, а каждая линия (полилиния) соединяет значения для одного объекта или группы во всех осях.
Области применения:
- Анализ многомерных данных: профили пользователей, товаров, производственных партий, сравнение характеристик конкурентов и др.
- Поиск схожих и аномальных объектов, выявление кластеров и outliers
- Визуализация динамики и структуры признаков для разных категорий
Структура данных:
- parallelAxis — массив объектов, каждый из которых задаёт одну ось (название, тип и пр.).
- series.data — массив массивов или объектов, где каждая вложенная последовательность содержит значения для всех осей.
Для примера рассмотрим изменение прибыли по годам для различных категорий продуктов.
Оператор данных:
function dataCal(originData) {
var dataModels = originData.dataModels;
var colData = dataModels[0].colData;
var data = [];
for (var i = 0; i < colData[0].length; i++) {
data[i] = {
year: colData[0][i],
product: colData[1][i],
value: colData[2][i]
};
}
return data;
}Оператор конфигураций:
function optionCal(data, chartConfig, chart) {
var years = [];
var products = [];
data.forEach(function(item) {
if (years.indexOf(item.year) === -1) years.push(item.year);
if (products.indexOf(item.product) === -1) products.push(item.product);
});
// Формируем массив для каждой линии: [value1, value2, ...]
var seriesData = products.map(function(product) {
return years.map(function(year) {
var found = data.find(function(item) {
return item.product === product && item.year === year;
});
return found ? Number(found.value) : null;
});
});
// Параллельные оси — года
var parallelAxis = years.map(function(year, idx) {
return { dim: idx, name: String(year), type: 'value' };
});
var colorPalette = [
"#5470C6", "#91CC75", "#EE6666", "#FAC858", "#73C0DE",
"#3BA272", "#FC8452", "#9A60B4", "#EA7CCC"
];
var lineColors = {};
products.forEach(function(product, idx) {
lineColors[product] = colorPalette[idx % colorPalette.length];
});
var option = {
title: { text: 'Parallel Chart Example', left: 'center' },
parallelAxis: parallelAxis,
parallel: { left: 80, right: 50, bottom: 50, top: 60 },
series: [{
type: 'parallel',
lineStyle: {
width: 3,
opacity: 0.7
},
data: seriesData.map(function(values, idx) {
return {
value: values,
lineStyle: {
color: colorPalette[idx % colorPalette.length],
width: 3,
opacity: 0.8
}
};
})
}],
legend: {
data: products,
left: 0,
top: 60,
orient: 'vertical',
textStyle: { fontSize: 14 }
},
tooltip: {
trigger: 'item',
formatter: function(params) {
var productIdx = params.dataIndex;
var product = products[productIdx];
var details = years.map(function(year, idx) {
var val = params.value[idx];
return '<br/>' + year + ': ' + (val != null ? Math.round(val) : '—');
}).join('');
return 'Продукт: ' + product + details;
}
}
};
return option;
}